package com.mvc;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mvc.annotation.RequestParam;
import com.mvc.annotation.Valid;
import com.mvc.handler.ParameterTypeHandler;
import com.mvc.handler.TypeHandlerManager;
import com.mysql.cj.log.Log;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Parameter;
import java.util.Map;

/**
 * 请求参数封装处理，全部集中到这个类里面来
 */
public class RequestParameterProcessor {
	
	private static ObjectMapper objectMapper;  // json转换
	
	public void setObjectMapper(ObjectMapper objectMapper) {
		RequestParameterProcessor.objectMapper = objectMapper;
	}
	
	
	
	// key - value 形式取值，直接从 request 获取  ，记住是  user.name   user.password 形式取值的
	// 这是递归构建 pojo 对象的
	private static Object getParameterValue(String parameterName, Class<?> type, HttpServletRequest request) throws InstantiationException,
			IllegalAccessException {
		ParameterTypeHandler<?> handler = TypeHandlerManager.getHandler(type);
		if (handler == null) {
			// 这个参数可能是一个对象， 不考虑 List Map 等等复杂类型了 ，只有普通的 Pojo 才行
			Object obj = type.newInstance();
			
			// 遍历对象字段进行查找
			Field[] fields = type.getDeclaredFields();
			for (Field field : fields) {
				Object tempVal = getParameterValue(parameterName + "." + field.getName(), field.getType(), request);
				field.setAccessible(true);
				field.set(obj, tempVal);
			}
			return obj;
		} else {
			String parameter = request.getParameter(parameterName);
			
			if (parameter == null) {
				return null;
			}
			return handler.getValue(parameter);
		}
	}
	
	// key - value 形式取值，直接从 request 获取
	public static Object parseFromRequestParameter(HttpServletRequest request, Parameter parameter, String paramName, Class<?> paramType) throws Exception {
		String[] parameterValues = request.getParameterValues(paramName);
		// 看下有没有  RequestParam
		if (parameter.isAnnotationPresent(RequestParam.class)) {
			RequestParam annotation = parameter.getAnnotation(RequestParam.class);
			
			// 如果注解name 属性不为空，且 按照原始参数名获取不到参数， 则用注解参数name 再获取一次
			if (!annotation.name().isEmpty() && parameterValues == null) {
				parameterValues = request.getParameterValues(annotation.name());
			}
			
			// 参数为空，则使用 注解中的默认值进行填充下
			if (parameterValues == null && !annotation.defaultValue().isEmpty()) {
				parameterValues = new String[]{annotation.defaultValue()};
			}
			
			// 检查 required  属性，必需参数为null 则抛异常
			if (annotation.required()) {
				if (parameterValues == null || parameterValues.length == 0) {
					throw new RuntimeException("请求参数缺少必要值");
				}
			}
		}
		
		// 开始转换值 String -> 参数类型,这里不管没有参数的问题了，必填参数要求通过 RequestParam(required = true) 来控制，不反复检查了
		// 不允许 char boolean byte short 这几个类型
		ParameterTypeHandler<?> handler = TypeHandlerManager.getHandler(paramType);
		if (handler != null) {
			return handler.getValue(parameterValues[0]);
		} else {
			// 其他类型一律当做bean 对待了
			Object obj = getParameterValue(paramName, paramType, request);
			
			return obj;
		}
	}
}
